# 在这里创建所需要的视图函数。
import logging
from flask import render_template, g, jsonify, abort, request
from info import db
from info.modules.models import News, User, Comment, CommentLike
from info.utils.common import set_func
from info.utils.response_code import RET
from . import news_blue
from info.modules import constants


# 这里是文章详情
@news_blue.route('/<news_id>')
@set_func
def news_detail(news_id):
    # 获取到用户的数据
    user = g.user
    # 我们在这里制作点击排行
    click_news = None
    try:
        click_news = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库出错啦')
    if not click_news:
        print('error')
    # 遍历得到结果
    news_list = []
    for news in click_news if click_news else []:
        news_list.append(news.to_basic_dict())

    # 查看模板中得字段，哪些是不能为空的
    news = None
    try:
        # 通过新闻的数据我们查询到所有新闻的数据
        news = News.query.get(news_id)
        # news = News.query.filter(News.id == news_id).all()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        abort(404)
    # 如果没有新闻数据，也返回404数据
    if not news:
        abort(404)
    # 加载一次详情页之后，我们的点击次数应该加一次
    try:
        news.clicks += 1
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='错误')

    # 我们在这里获取到新闻的评论
    comm = None
    try:
        comm = Comment.query.filter(Comment.news_id == news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库一不小心出错啦')

    # 我们在这里遍历得到的评论数据
    comments = []
    comment_count = 0
    for comment in comm:
        comment_count += 1
        comments.append(comment.to_dict())

    # 判断是否点赞的思路
    '''
        首先需要取出所有这条新闻下面的评论
        获取所有的评论id
        获得当前这个用户的所有的评论
        获得用户点赞的评论id
        然后将所有的id遍历,并改为false
        如果遍历的评论id在那个用户点赞的id集里面
        就改成true
    '''
    # 我们在这里判断用户是否点赞了
    comment_list = []
    if user:

        # 获取当前这个用户所有的评论
        comment_like_ids =[]
        comments_liked = None
        try:
            # 获取所有评论的id
            comment_ids = [comment.id for comment in comm]
            comments_liked = CommentLike.query.filter(CommentLike.comment_id.in_(comment_ids), CommentLike.user_id == g.user.id).all()
            # 取出所有的id
            comment_like_ids = [comment_likes.comment_id for comment_likes in comments_liked]
        except Exception as e:
            # 用日志记录
            logging.error(e)

        # 遍历所有的评论如果评论id在用户点赞的那个评论里面就改为true
        for item in comm if comm else []:
            # 将模型转为字典
            item_dict = item.to_dict()
            item_dict['is_like'] = False

            if user and item.id in comment_like_ids:
                item_dict['is_like'] = True
            comment_list.append(item_dict)

    # 这里我们判断用户是否收藏过数据
    # 先定义个is——collected
    is_collected = False
    if user:  # 我们判断用户是否登录
        if news in user.collection_news:
            is_collected = True

    # 我们在这类决定是否关注该作者了
    is_followed = False
    if user and news.user:
        if user in news.user.followers:
            is_followed = True

    data = {
        'news': news.to_dict(),
        'news_list': news_list,
        'is_collected': is_collected,
        'user': user.to_index_dict() if user else None,
        'count': comment_count,
        'comment_list': comment_list,
        'is_followed': is_followed
    }
    return render_template('news/detail.html', data=data)


# 我们这里写收藏与取消收藏
'''
收藏与取消收藏的步骤
1.首先获取用户的id，判断用户是否是登录状态，如果不是登录状态，则要求登录
2.如果用户是登录状态的，我们就判断用户是否收藏过这个新闻，如果收藏过，我们就
让网页上的收藏显示已经收藏，否则显示没有收藏
'''


@news_blue.route('/news_collect', methods=["POST"])
@set_func
def collection():
    # 获取参数
    # 从前端获得news_id， collect， 从user中获得user——id
    user = g.user
    news_id = request.json.get('news_id')
    collect = request.json.get('action')

    # 首先判断用户有没有登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='cuowu ')
    # 判断有没有值
    user_id = user.id
    if not all([user_id, news_id, collect]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不全')

    # 逻辑处理
    try:
        user = User.query.filter(User.id == user_id).first()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')

    try:
        news = News.query.filter(News.id == news_id).first()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')

    # 判断用户有没有收藏过这个新闻，
    if collect == 'collect':
        # 判断新闻在不在用户的收藏列表里面
        if news not in user.collection_news:
            user.collection_news.append(news)
    if collect == 'cancel_collect':
        # 判断新闻在不在用户新闻列表中
        if news in user.collection_news:
            user.collection_news.remove(news)

    # 提交数据库
    try:
        db.session.commit()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='提交失败')

    return jsonify(errno=RET.OK, errmsg='ok')

# 我们在这里写用户评论的功能
'''
    用户评论，必须的几个参数，用户id，新闻id，评论内容，父级评论的id没有的话就表示就是第一层评论
    用户id 从set_func中取，新闻id，和评论内容，父级评论的id都是从前端中取
    需要判断参数的完整性，
    查询新闻和用户是否存在，这个基本上都是要判断的。在将评论加进去之前我们需要判断
    新闻和用户是否存在。
    创建评论的模型，提交数据库
    返回ok
    
'''


@news_blue.route('/news_comment', methods=['POST'])
@set_func
def news_comment():
    # 首先通过g.user获得用户数据
    user = g.user
    # 判断用户是否存在
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='user need to login in')

    # 从前端获取参数
    news_id = request.json.get('news_id')
    content = request.json.get('comment')
    parent_id = request.json.get('parent_id')

    # 判断参数完整性
    if not all([news_id, content]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')

    # 判断新闻是否存在
    try:
        news = News.query.filter(News.id == news_id).first()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='新闻不存在')

    # 新闻如果存在，用户也存在，
    # 我们就创建模型，先创建评论的对象
    comm = Comment()
    comm.user_id = user.id
    comm.news_id = news.id
    comm.content = content
    comm.parent_id = parent_id

    # 提交数据库
    try:
        db.session.add(comm)
        db.session.commit()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')

    return jsonify(errno=RET.OK, errmsg='ok', data=comm.to_dict())


# 定义一个评论点赞的路由
'''
    评论点赞，我们通过model知道一共有两个字段，全部都不能为空
    一个是user_id。一个是news_id，评论id
    news_id需要从前端获取，user_id从set_func中获取。
    校验参数不为空，我们还是要判断用户和新闻存不存在，
    用户在set_func中判断好了，
    之后通过false和true判断到底是点赞还是取消点赞，
    判断的时候还需要判断该条评论在不在我们的已经点赞的列表里面了，
    这个和收藏与取消收藏一样。
'''


@news_blue.route('/comment_like', methods=['POST'])
@set_func
def comments_like():
    # 获取参数
    user = g.user
    comment_id = request.json.get('comment_id')
    action = request.json.get('action')
    # 校验参数
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')

    if not all([action, comment_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='出错啦,')

    # 逻辑处理
    # 检验评论和新闻是否存在
    try:
        comment = Comment.query.filter(Comment.id == comment_id).first()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='评论不存在')

    if not comment:
        return jsonify(errno=RET.DBERR, errmsg='评论不存在')

    comment_like_ = CommentLike.query.filter(CommentLike.comment_id == comment_id, User.id == user.id).first()

    if action == 'add':
        # 我们需要判断点赞表里面有没有这条评论
        if not comment_like_:
            # 如果用户没有点赞过,我们就添加一个模型
            comment_like = CommentLike()
            comment_like.user_id = user.id
            comment_like.comment_id = comment_id
            db.session.add(comment_like)
            # 点赞数加一
            comment.like_count += 1

        else:
            # 这边就是已经点过赞,现在取消点赞了
            try:
                db.session.delete(comment_like_)
                # 点赞数减一
                comment.like_count -= 1
            except Exception as e:
                db.session.rollback()
                # 用日志记录
                logging.error(e)

    try:
        # db.session.add(comment_like)
        db.session.commit()
        # db.session.commit()
    except Exception as e:
        db.session.rollback()
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='操作失败')

    return jsonify(errno=RET.OK, errmsg='OK')


# 这里写新闻详情页用户的名片

'''
这里如果是个人发布的由名片,如果不是个人发布的,就没有名片
取到目标用户的id 和我的action
判断用户存不存在
并且
'''


@news_blue.route('/followed_user', methods=['GET', 'POST'])
@set_func
def followed_user():
    # 先判断用户在不在
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='请登录')

    # 获取参数
    user_id = request.json.get('user_id')
    action = request.json.get('action')

    # 校验参数
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
    if action not in ('follow', 'unfollow'):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    # 查询用户在不在
    try:
        target_user = User.query.get(user_id)
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='无此用户')

    if not target_user:
        return jsonify(errno=RET.DBERR, errmsg='无此用户')

    # 判断是否已经有过这个用户了
    if action == 'follow':
        if target_user.followers.filter(User.id == user.id).first():
            return jsonify(errno=RET.DATAEXIST, errmsg='已经关注过此用户了')
        target_user.followers.append(user)
    else:
        if target_user.followers.filter(User.id == user.id).first():
            target_user.followers.remove(user)

    # 提交数据库
    try:
        db.session.commit()
    except Exception as e:
        # 用日志记录
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')

    # 返回数据
    return jsonify(errno=RET.OK, errmsg='OK')





